//
// itertool - a polynormial and type-safe iterator framework in C++.
//
// Copyright (c) 2021-2025 Feng Cong
//
// Distributed under the MIT Software License
// See accompanying file LICENSE.txt or copy at
// https://opensource.org/licenses/MIT

#include <itertool/iter/seq.h>

#include <algorithm>
#include <vector>

#include "itertool_test.h"

TEST_SUITE("Seq") {
  TEST_CASE("Adapt std::vector") {
    const int kValue = 32;
    const size_t kSize = 10;
    std::vector<int> vi(kSize, kValue);
    auto seq = itertool::Seq(vi.begin(), vi.end());

    SUBCASE("Seq(first, last) signature") {
      int i = 0;
      for (auto val : seq) {
        CHECK_EQ(val, kValue);
        i++;
      }
      CHECK_EQ(i, kSize);
    }

    SUBCASE("Seq(c) signature") {
      auto seq = itertool::Seq(vi);
      int i = 0;
      for (auto val : seq) {
        CHECK_EQ(val, kValue);
        i++;
      }
      CHECK_EQ(i, kSize);
    }

    SUBCASE("ItemType is mutable") {
      const int kOtherValue = 11;
      auto seq = itertool::Seq(vi);
      std::fill(seq.begin(), seq.end(), kOtherValue);
      auto rv = std::all_of(vi.begin(), vi.end(),
                            [=](int val) { return val == kOtherValue; });
      CHECK(rv);
    }

    SUBCASE("LengthHint and other optional methods") {
      CHECK_EQ(seq.LengthHint(), vi.size());
      CHECK(seq.IsFinite());
      CHECK(seq.IsResetable());
      seq.Reset();
    }
  }

#if 0
  TEST_CASE(
      "When requirements not met, a compiler error message should show up") {
    struct BadIter {
      BadIter() = default;
      int operator*() { return 0; }
      bool operator!=(const BadIter&) const { return false; }
    };
    auto it = itertool::Seq(BadIter(), BadIter());
  }
#endif
}
